package program.commands;

import be.kuleuven.cs.som.annotate.*;
import item.*;

/**
 * A class for dealing with sequences: (seq(command)(command)...).
 *
 * @invar	The array of commands of each selection must be a valid list of commands.
 *                      | canHaveAsCommands(getCommands())
 *
 */
public class Sequence extends Commands {
	private final Commands[] commands;
	
	/**
	 * Initialise this new sequence with a line number and an array of commands.
	 *
	 * @param	commands
	 *                      The list of commands which the sequence has to execute.
	 * @pre         The given array of commands must be valid.
	 *                      | canHaveAsCommands(commands)
	 * @post        The array of commands of this sequence is set to the given array of commands.
	 *                      | new.getCommands() == commands
	 */
	public Sequence(int lineNb, Commands[] commands) {
		super(lineNb);
		assert(canHaveAsCommands(commands));
		this.commands = commands;
	}
	
	/**
	 * Returns the array of commands of this sequence.
	 */
	@Basic @Raw @Immutable
	public Commands[] getCommands() {
		return commands;
	}
	
	/**
	 * Checks whether a given list of commands is a valid one for a sequence.
	 *
	 * @param	commands
	 *                      The list of commands to check for whether it is a valid one.
	 * @return    
	 *         | if(commands == null)
	 *         |       then result == false
	 * @return      
	 *         | for one command in commands :
	 *         |       if(command == null)
	 *         |               then result == false
	 *         | result == true
	 */
	@Raw
	public boolean canHaveAsCommands(Commands[] commands) {
		if(commands == null)
			return false;
		for(Commands command : commands)
			if(command == null)
				return false;
		return true;
	}
	
	/**
	 * Returns a textual representation of this sequence,
	 * formatted in accordance with its position in the program.
	 *
	 * @return	
	 *          | result ==
	 *          |       getIndentation(indentationLevel) + "(seq\n" +
	 *          |       { for each command in getCommands():
	 *          |               command.prettyFormat(indentationLevel+1) + "\n"
	 *          |       }
	 *          |       + getIndentation(indentationLevel) + ")"
	 */
	@Override
	public String prettyFormat(int indentationLevel) {
		String commandList = "";
		for(Commands command : getCommands())
			commandList += command.prettyFormat(indentationLevel+1) + "\n";
		return getIndentation(indentationLevel) + "(seq\n" + commandList + getIndentation
				(indentationLevel) + ")";
	}
	
	/**
	 * Returns the next basic command for a robot, given the last executed line number.
	 *
	 * @return      
	 *         | if( lineNb >= getLineNb() )
	 *         |       then result == false
	 * @return      
	 *         | for one i in commands.length :
	 *         |       if( getCommands()[i].getNextBasicCommand(lineNb, robot) != null)
	 *         |               then result == getCommands()[i].getNextBasicCommand(lineNb, robot)
	 *         |       else
	 *         |               then result == null
	 */
	@Override
	public BasicCommand getNextBasicCommand(int lineNb, Robot robot) {
		if(lineNb >= getLineNb())
			return null;
		for(int i = 0; i < commands.length; i++) {
			BasicCommand next = getCommands()[i].getNextBasicCommand(lineNb, robot);
			if(next != null) return next;
		}
		return null;
	}
}